//微信聊天可视化组件
//依赖scrollLoader组件, 依赖指令v-emotion（实现请查看main.js）

// 参数：
// width               组件宽度，默认450
// wrapBg              外层父元素背景颜色，默认#efefef
// maxHeight           展示窗口最高高度, 默认900
// contactAvatarUrl    好友头像url
// ownerAvatarUrl      微信主人头像url
// ownerNickname       微信主人昵称
// getUpperData        （必需）当滚动到上方时加载数据的方法，返回值要为Promise对象，resolve的结构同data
// getUnderData        （必需）当滚动到下方时加载数据的方法，返回值同上
// data                （必需）传入初始化数据， 结构如下：
// [{
//     direction: 2, //为2表示微信主人发出的消息，1表示联系人
//     id: 1, //根据这个来排序消息
//     type: 1, //1为文本，2为图片
//     content: '你好!![呲牙]', //当type为1时这里是文本消息，当type2为2时这里要存放图片地址；后续会支持语音的显示
//     ctime: new Date().toLocaleString() //显示当前消息的发送时间
// },
// {
//     direction: 1,
//     id: 2,
//     type: 1,
//     content: '你也好。[害羞]',
//     ctime: new Date().toLocaleString()
// }]

<template>
  <div class="wxchat-container" :style="{ backgroundColor: wrapBg }">
    <div
      class="window"
      id="window-view-container"
      :style="{ maxHeight: maxHeight + 'px', width: width + 'px' }"
    >
      <div>nihao</div>
      <!-- data is empty -->
      <div class="loading" v-if="dataArray && dataArray.length == 0">
        <div style="margin-top: 300px; text-align: center; font-size: 16px">
          <span>未查找到聊天记录</span>
        </div>
      </div>

      <!-- loading -->
      <div class="loading" v-if="dataArray.length == 0">
        <div style="margin-top: 300px">
          <div>加载中...</div>
        </div>
      </div>

      <div class="title" v-if="dataArray && dataArray.length > 0">
        <p v-text="contactNickname"></p>
      </div>
      <!-- main -->
      <ScrollLoader
        :minHeight="minHeight"
        @scroll-to-top="refresh"
        @scroll-to-botton="infinite"
        class="container-main"
        v-if="dataArray && dataArray.length > 0"
        :style="{ maxHeight: maxHeight - 50 + 'px' }"
      >
        <div class="message">
          <ul>
            <li
              v-for="message in dataArray"
              :key="message.id"
              :class="message.direction == 2 ? 'an-move-right' : 'an-move-left'"
            >
              <p class="time"><span v-text="message.ctime"></span></p>
              <p class="time system" v-if="message.type == 10000">
                <span v-html="message.content"></span>
              </p>
              <div
                :class="'main' + (message.direction == 2 ? ' self' : '')"
                v-else
              >
                <img
                  class="avatar"
                  width="45"
                  height="45"
                  :src="
                    message.direction == 2 ? ownerAvatarUrl : contactAvatarUrl
                  "
                />
                <!-- 文本 -->
                <div
                  class="text"
                  v-emotion="message.content"
                  v-if="message.type == 1"
                ></div>

                <!-- 图片 -->
                <div class="text" v-else-if="message.type == 2">
                  <img :src="message.content" class="image" alt="聊天图片" />
                </div>

                <!-- 其他 -->
                <div
                  class="text"
                  v-else-if="message.type != 10000"
                  v-text="
                    '[暂未支持的消息类型:' +
                    message.type +
                    ']\n\r' +
                    message.content
                  "
                ></div>
              </div>
            </li>
          </ul>
        </div>
      </ScrollLoader>
    </div>
  </div>
</template>

<script>
import ScrollLoader from "./ScrollLoader.vue";

export default {
  name: "wxChat",

  components: {
    ScrollLoader,
  },

  props: {
    contactNickname: {
      type: String,
      default: "Mystic Faces",
    },

    data: {
      type: Array,
      required: true,
    },

    width: {
      type: Number,
      default: 450,
    },

    wrapBg: {
      type: String,
      default: "#efefef",
    },

    maxHeight: {
      type: Number,
      default: 700,
    },

    contactAvatarUrl: {
      type: String,
    },

    ownerAvatarUrl: {
      type: String,
    },

    getUpperData: {
      type: Function,
      required: true,
    },

    getUnderData: {
      type: Function,
      required: true,
    },
  },

  data() {
    return {
      isUpperLaoding: false,
      isUnderLaoding: false,

      isRefreshedAll: false,
      isLoadedAll: false,

      minHeight: 700,
      dataArray: [],
    };
  },

  created() {
    this.initData();
    console.log("*********************************");
    console.log(this.data);
    console.log(this.contactNickname);
    console.log(this.getUpperData);
    console.log(this.getUnderData);
    console.log(this.ownerAvatarUrl);
    console.log(this.contactAvatarUrl);
    console.log(this.width);
    console.log("*********************************");
    console.log(this.dataArray);
    console.log("*********************************");
  },
  mounted() {
    //document.getElementsByTagName('body')[0].scrollTop=0;
    // this.minHeight = document.getElementById('window-view-container').offsetHeight;
    // this.maxHeight = document.getElementById('window-view-container').offsetHeight;
  },

  methods: {
    initData() {
      this.dataArray = this.dataArray.concat(this.data);
    },

    //向上拉刷新
    refresh(done) {
      var me = this;
      if (me.isUpperLaoding) {
        return;
      }

      if (me.isRefreshedAll) {
        done(true);
        me.isUpperLaoding = false;
        return;
      }

      try {
        this.getUpperData().then(function (data) {
          if (data.length == 0) {
            me.isRefreshedAll = true;
            done(true);
          } else {
            me.dataArray = data.reverse().concat(me.dataArray); //倒序合并
            done();
          }
        });
      } catch (error) {
        console.error(
          'wxChat: props "getUpperData" must return a promise object!'
        );
      }
      me.isUpperLaoding = false;
    },

    //向下拉加载
    infinite(done) {
      var me = this;
      if (me.isUnderLaoding) {
        return;
      }
      if (me.isLoadedAll) {
        done(true);
        me.isUnderLaoding = false;
        return;
      }

      try {
        this.getUnderData().then(function (data) {
          if (data == 0) {
            me.isLoadedAll = true;
            done(true);
          } else {
            done();
            me.dataArray = me.dataArray.concat(data); //直接合并
          }
        });
      } catch (error) {
        console.error(
          'wxChat: props "getUnderData" must return a promise object!'
        );
      }
      me.isUnderLaoding = false;
    },
  },
};
</script>


<style scoped>
.wxchat-container {
  width: 100%;
  height: 100%;
  z-index: 100;
  position: fixed;
  left: 0;
  top: 0;
  overflow: hidden;
}
.shadow {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  width: 100%;
  height: 100%;
  background: #000;
  opacity: 0.2;
}
.window {
  box-shadow: 1px 1px 20px -5px #000; /*max-width: 450px;*/
  min-width: 300px;
  background: #f5f5f5;
  margin: 0 auto;
  overflow: hidden;
  padding: 0;
  height: 100%;
  position: relative;
  z-index: 101;
}
button {
  border: 0;
  background: none;
  border-radius: 0;
  text-align: center;
}
button {
  outline: none;
}
.w100 {
  width: 100%;
}
.mt5 {
  margin-top: 5px;
}
.mt10 {
  margin-top: 10px;
}
.mt20 {
  margin-top: 20px;
}
.mb10 {
  margin-bottom: 10px;
}
.mb20 {
  margin-bottom: 20px;
}
.fs0 {
  font-size: 0;
}
.title {
  background: #000;
  text-align: center;
  color: #fff;
  width: 100%;
  height: 50px;
  line-height: 50px;
  font-size: 14px;
}
.loading,
.no-more {
  text-align: center;
  color: #b0b0b0;
  line-height: 100px;
}
.no-more {
  line-height: 60px;
}
.pull-right {
  float: right;
}
.link-line {
  text-decoration: underline;
}
.message {
  /*height: 100%;*/
  padding: 10px 15px;
  /*overflow-y: scroll;*/
  background-color: #f5f5f5;
}
.message li {
  margin-bottom: 15px;
  left: 0;
  position: relative;
  display: block;
}
.message .time {
  margin: 10px 0;
  text-align: center;
}
.message .text {
  display: inline-block;
  position: relative;
  padding: 0 10px;
  max-width: calc(100% - 75px);
  min-height: 35px;
  line-height: 2.1;
  font-size: 15px;
  padding: 6px 10px;
  text-align: left;
  word-break: break-all;
  background-color: #fff;
  color: #000;
  border-radius: 4px;
  box-shadow: 0px 1px 7px -5px #000;
}
.message .avatar {
  float: left;
  margin: 0 10px 0 0;
  border-radius: 3px;
  background: #fff;
}
.message .time > span {
  display: inline-block;
  padding: 0 5px;
  font-size: 12px;
  color: #fff;
  border-radius: 2px;
  background-color: #dadada;
}
.message .system > span {
  padding: 4px 9px;
  text-align: left;
}
.message .text:before {
  content: " ";
  position: absolute;
  top: 9px;
  right: 100%;
  border: 6px solid transparent;
  border-right-color: #fff;
}
.message .self {
  text-align: right;
}
.message .self .avatar {
  float: right;
  margin: 0 0 0 10px;
}
.message .self .text {
  background-color: #9eea6a;
}

.message .self .text:before {
  right: inherit;
  left: 100%;
  border-right-color: transparent;
  border-left-color: #9eea6a;
}
.message .image {
  max-width: 200px;
}
img.static-emotion-gif,
img.static-emotion {
  vertical-align: middle !important;
}

.an-move-left {
  left: 0;
  animation: moveLeft 0.7s ease;
  -webkit-animation: moveLeft 0.7s ease;
}
.an-move-right {
  left: 0;
  animation: moveRight 0.7s ease;
  -webkit-animation: moveRight 0.7s ease;
}
.bgnone {
  background: none;
}
@keyframes moveRight {
  0% {
    left: -20px;
    opacity: 0;
  }
  100% {
    left: 0;
    opacity: 1;
  }
}

@-webkit-keyframes moveRight {
  0% {
    left: -20px;
    opacity: 0;
  }
  100% {
    left: 0px;
    opacity: 1;
  }
}
@keyframes moveLeft {
  0% {
    left: 20px;
    opacity: 0;
  }
  100% {
    left: 0px;
    opacity: 1;
  }
}

@-webkit-keyframes moveLeft {
  0% {
    left: 20px;
    opacity: 0;
  }
  100% {
    left: 0px;
    opacity: 1;
  }
}

@media (max-width: 367px) {
  .fzDInfo {
    width: 82%;
  }
}
</style>








// ******************************************************************************************************************************************************************************


//主文件，对wxChat的用法做示例

<template>
  <wxChat
    :data="wxChatData"
    showShade="false"
    contactNickname="简叔Nihao"
    :getUpperData="getUpperData"
    :getUnderData="getUnderData"
    :ownerAvatarUrl="ownerAvatarUrl"
    :contactAvatarUrl="contactAvatarUrl"
    :width="width"
  >
  </wxChat>
</template>

<script>
import wxChat from "../../components/chat/ChatBox.vue";

export default {
  name: "app",
  data() {
    return {
      upperTimes: 0,
      underTimes: 0,
      upperId: 0,
      underId: 6,
      width: window.screen.width,
      ownerAvatarUrl: "../../assets/login2.jpg",
      contactAvatarUrl: "../../assets/login2.jpg",
      wxChatData: [
        {
          direction: 2,
          id: 1,
          type: 1,
          content: "你好!![呲牙]",
          ctime: new Date().toLocaleString(),
        },
        {
          direction: 1,
          id: 2,
          type: 1,
          content: "你也好。[害羞]",
          ctime: new Date().toLocaleString(),
        },
        {
          direction: 2,
          id: 3,
          type: 1,
          content: "这是我的简历头像：",
          ctime: new Date().toLocaleString(),
        },
        {
          direction: 2,
          id: 4,
          type: 2,
          content: "./src/assets/wyz.jpg",
          ctime: new Date().toLocaleString(),
        },
        {
          direction: 1,
          id: 5,
          type: 1,
          content: "你开心就好。[微笑]",
          ctime: new Date().toLocaleString(),
        },
      ],
    };
  },
  components: { wxChat },
  created() {
    this.initWidth();
  },
  methods: {
    initWidth() {
      var ua = navigator.userAgent;
      var ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
        isIphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
        isAndroid = ua.match(/(Android)\s+([\d.]+)/),
        isMobile = isIphone || isAndroid;
      //非移动端设置400px宽度，移动端是100%
      if (!isMobile) {
        this.width = 400;
      }
    },

    //向上滚动加载数据
    getUpperData() {
      var me = this;

      // 这里为模拟异步加载数据
      // 实际上你可能要这么写:
      // return axios.get('xxx').then(function(result){
      //     return result;  //result的格式需要类似下面resolve里面的数组
      // })
      return new Promise(function (resolve) {
        setTimeout(function () {
          //模拟加载完毕
          if (me.upperTimes > 3) {
            return resolve([]);
          }

          //加载数据
          resolve([
            {
              direction: 2,
              id: me.upperId - 1,
              type: 1,
              content: "向上滚动加载第 " + me.upperTimes + " 条！",
              ctime: new Date().toLocaleString(),
            },
            {
              direction: 1,
              id: me.upperId - 2,
              type: 1,
              content: "向上滚动加载第 " + me.upperTimes + " 条！",
              ctime: new Date().toLocaleString(),
            },
          ]);
        }, 1000);
        me.upperId = me.upperId + 2;
        me.upperTimes++;
      });
    },

    getUnderData() {
      var me = this;

      //意义同getUpperData()
      return new Promise(function (resolve) {
        setTimeout(function () {
          //模拟加载完毕
          if (me.underTimes > 3) {
            return resolve([]);
          }

          //加载数据
          resolve([
            {
              direction: 1,
              id: me.underId + 1,
              type: 1,
              content: "向下滚动加载第 " + me.underTimes + " 条！",
              ctime: new Date().toLocaleString(),
            },
            {
              direction: 2,
              id: me.underId + 2,
              type: 1,
              content: "向下滚动加载第 " + me.underTimes + " 条！",
              ctime: new Date().toLocaleString(),
            },
          ]);
        }, 1000);

        me.underId = me.underId + 2;
        me.underTimes++;
      });
    },
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

h1,
h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
}
</style>
